import workerpool from "workerpool"
import { input } from "@inquirer/prompts"
import logger from "./component/logger.js"
import frpOption from "./option.json" with { type: "json" }

import LocalOldOrderList from './pendingOrder.json' with { type: "json" }
import { setErrorLog } from "./component/util.js"

import ora from 'ora'

import fs from "fs"
const fsPromises = fs.promises
const errorOrderCodeFile = "./errorOrderCode.txt"
async function setErrorOrderCode(orderCode, errMsg) {
    await fsPromises.appendFile(errorOrderCodeFile, `${orderCode} ${errMsg}\n`, { encoding: "utf8" })
}

const mainWorker = "./mainWorker.js"

async function multiThreadingRun() {
    let pool
    let spinner
    try {
        const maxWorkersStr = await input({ message: "Enter max workers number", required: true })
        const maxWorkers = parseInt(maxWorkersStr)

        if (Number.isNaN(maxWorkers) || maxWorkers <= 0) {
            throw new Error('请输入正确的数字')
        }

        logger.info("开始批量执行")

        spinner = ora('正在批量进行流程').start()

        pool = workerpool.pool(mainWorker, {
            maxWorkers: maxWorkers,
        })

        let successCount = 0
        let runCount = 0

        const oneTimeLimit = Math.max(maxWorkers, 50)
        let offset = 0
        let total = 1

        while (offset < total) {
            // const data = await getOldOrderList(offset, oneTimeLimit)
            const data = await getLocalOldOrderList(offset, oneTimeLimit)
            total = data.total || 0
            offset += data.data?.length || 0

            const oldOrderList = data.data

            const workerList = []
            for (const order of oldOrderList) {
                const promise = pool
                    .exec("run", [order.code, order.oldCode])
                    .then(async () => {
                        successCount += 1
                        logger.info(`${order.code} 执行流程完成`)
                    })
                    .catch(async (err) => {
                        try {
                            await setErrorLog(order.code, order.oldCode, err.message)
                            await setErrorOrderCode(order.code, err.message)
                        } catch (e) {
                            logger.error(`提交远程错误日志失败: ${e.message}`)
                        }
                        logger.error(`${order.code} ${err.message}`)
                    })
                    .finally(async () => {
                        runCount += 1
                    })
                workerList.push(promise)
            }

            await Promise.all(workerList)
        }

        const finishText = `全部执行完成 本次执行数量${runCount} 成功数量${successCount}`
        spinner?.succeed(finishText)
        logger.info(finishText)
    } catch (e) {
        spinner?.info(e.message)
        logger.error(e.message)
    } finally {
        spinner?.stop()
        pool?.terminate()
    }
}

async function getOldOrderList(offset, limit) {
    const retryTotal = 5
    let retryTime = 0
    while (retryTime < retryTotal) {
        let res = await fetch(frpOption.api.getOldOrderList, {
            method: "POST",
            body: JSON.stringify({
                offset: offset,
                limit: limit,
            }),
        })
        const json = await res.json()
        if (json.code !== 200) {
            retryTime++
            logger.error("获取旧数据失败：" + (json.reason || JSON.stringify(json)))
            continue
        }
        return json
    }
    throw new Error("获取旧数据失败")
}

async function getLocalOldOrderList(offset, limit) {
    return {
        total: LocalOldOrderList.length,
        data: LocalOldOrderList.slice(offset, offset + limit)
    }
}

await multiThreadingRun()
